#include <stdio.h>

#include <util/common_macros.h>
#include <util/mem.h>

#include "edge.h"
#include "triangle.h"

/* ========================================================================== */

static long int count = 0;

/* ========================================================================== */

static boolean __edge_destroy(ImpObject * object) {
	ImpEdge * e;
	ListIterator * it;

	e = IMP_EDGE(object);

	it = e->faces->first;
	while (it) {
		imp_object_destroy(IMP_OBJECT(it->data));
		it = it->next;
	}

	if (e->faces) {
		list_remove_all_data(e->faces);
		list_delete(e->faces);
	}
	e->faces = NULL;
	
	return TRUE;
}
static void __edge_class_init(ImpObjectClass * klass) {
	klass->object_clone = NULL;
	klass->object_destroy = __edge_destroy;
	klass->object_attributes = NULL;
}
static void __edge_init(ImpObject * object) {
	ImpEdge * e;
	e = IMP_EDGE(object);
	e->faces = NULL;
}

/* ========================================================================== */

ImpEdgeClass * imp_edge_get_class(void) {
	static ImpEdgeClass * klass = NULL;

	if (klass == NULL) {
		ImpObjectClassInfo edge_info = {
			"ImpEdge",
			sizeof (ImpEdge),
			sizeof (ImpEdgeClass),
			(ImpObjectClassInitFunc) __edge_class_init,
			(ImpObjectInitFunc) __edge_init,
			(ImpArgSetFunc) NULL,
			(ImpArgGetFunc) NULL
		};

		ImpObjectClass * parent_class = IMP_OBJECT_CLASS(imp_segment_get_class());
		ImpObjectClass * edge_class = imp_object_class_new(parent_class, &edge_info);
		klass = IMP_EDGE_CLASS(edge_class);
	}
	return klass;
}
ImpEdge * imp_edge_new(ImpVertex * v1, ImpVertex * v2) {

	ImpEdge * e;

	e = IMP_EDGE(imp_object_new(IMP_OBJECT_CLASS(imp_edge_get_class())));
	e->faces = list_new();

	imp_edge_set(e, v1, v2);
	
	count++;

	return e;
}
void imp_edge_set(ImpEdge * e, ImpVertex * v1, ImpVertex * v2) {
	imp_segment_set(IMP_SEGMENT(e), v1, v2);
}

/* ========================================================================== */

void imp_edge_add_triangle(ImpEdge * e, ImpTriangle * t) {

	list_insert(e->faces, t);

}
ImpTriangle * imp_edge_remove_triangle(ImpEdge * e, ImpTriangle * t) {

	return list_remove_data(e->faces, t);

}

/* ========================================================================== */

inline void imp_edge_extract_points(ImpEdge * e1, ImpPoint ** p1, ImpPoint ** p2) {
	*p1 = IMP_POINT(IMP_SEGMENT(e1)->v[0]);
	*p2 = IMP_POINT(IMP_SEGMENT(e1)->v[1]);
}
inline void imp_edge_extract_vertices(ImpEdge * e1, ImpVertex ** v1, ImpVertex ** v2) {
	*v1 = IMP_SEGMENT(e1)->v[0];
	*v2 = IMP_SEGMENT(e1)->v[1];
}

/* ========================================================================== */

void imp_edge_print(ImpEdge * e) {

	if (!e) {
		printf("[NULL]");
		return;
	}

	printf("[");
	imp_vertex_print(IMP_SEGMENT(e)->v[0]);
	printf("  ");
	imp_vertex_print(IMP_SEGMENT(e)->v[1]);
	printf("]");

}
